package com.moviesearch.elastic7.service.impl;

import com.alibaba.fastjson.JSON;
import com.moviesearch.elastic7.mapper.FilmresourcesMapper;
import com.moviesearch.elastic7.model.Filmresources;
import com.moviesearch.elastic7.service.ElasticService;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

@Service
public class ElasticServiceImpl implements ElasticService {
    @Resource
    private RestHighLevelClient restHighLevelClient;
    @Resource
    private FilmresourcesMapper filmresourcesMapper;

    //数据库数据导入(批量添加数据)
    /**
     *
     * @param index
     * @return
     * @throws IOException
     */
    @Override
    public String mysqlToEs(String index) throws IOException {
        //查询出所有数据
        List<Filmresources> filmresourcess = filmresourcesMapper.selectByExample(null);
        //创建Es批量对象
        BulkRequest bulkRequest = new BulkRequest();
        if(filmresourcess!=null&&filmresourcess.size()>0){
            for(Filmresources filmresources:filmresourcess){
                IndexRequest indexRequest = new IndexRequest(index);
                indexRequest.source(JSON.toJSONString(filmresources), XContentType.JSON);
                bulkRequest.add(indexRequest);
            }
        }
        //执行插入操作
        restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
        return "success";
    }

    //新增一条数据
    /**
     *
     * @param filmresources
     * @param index
     * @return
     * @throws IOException
     */
    @Override
    public String insertEs(Filmresources filmresources,String index) throws IOException {
        IndexRequest indexRequest = new IndexRequest(index);
        indexRequest.source(JSON.toJSONString(filmresources), XContentType.JSON);
        restHighLevelClient.index(indexRequest,RequestOptions.DEFAULT);
        return "success";
    }


    //修改一条数据
    /**
     *
     * @param filmresources
     * @param index
     * @param id
     * @return
     * @throws IOException
     */
    @Override
    public String updateEs(Filmresources filmresources,String index,String id) throws IOException {
        UpdateRequest updateRequest = new UpdateRequest(index, id);
        updateRequest.doc(JSON.toJSONString(filmresources), XContentType.JSON);
        restHighLevelClient.update(updateRequest,RequestOptions.DEFAULT);
        return "success";
    }

    /*根据esid查看数据*/
    /**
     *
     * @param index
     * @param esid
     * @return
     * @throws IOException
     */
    @Override
    public Filmresources getEs(String index, String esid) throws IOException {
        GetRequest getRequest = new GetRequest(index, esid);
        GetResponse documentFields = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
        Filmresources filmresources = JSON.parseObject(documentFields.getSourceAsString(), Filmresources.class);
        return filmresources;
    }

    /*根据esid删除一条信息*/
    public String deleteEs(String index,String esid) throws  IOException{
        DeleteRequest deleteRequest = new DeleteRequest(index);
        deleteRequest.id(esid);
        restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
        return "success";
    }

    /*关键词条件搜索*/
    /**
     *
     * @param index  Es的index
     * @param keyword 用户搜索的关键词信息
     * @param pageIndex 查询的页数
     * @param pageCount 每页的数量
     * @param fields  参与搜索的字段名称
     * @return
     */
    public List<Filmresources> getByCondition(String index,String keyword ,Integer pageIndex,Integer pageCount,String... fields) throws IOException {
        //创建查询对象
        SearchRequest searchRequest = new SearchRequest(index);
        //创建条件查询对象
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        //条件拼接对象
        BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery();

        //关键词以及查询字段导入
        MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(keyword, fields);
        //区间查询
        RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("filmscoring");
        rangeQueryBuilder.gt(8.0);
        rangeQueryBuilder.lt(9.7);
        //将所有的查询条件合并
        //must表示and ,should表示or,notmust表示not
        boolBuilder.must(multiMatchQueryBuilder);
        boolBuilder.must(rangeQueryBuilder);
        sourceBuilder.query(boolBuilder);

        //分页查询
        //页数与每页数量计算从那条记录开始
        Integer fromMessage = pageIndex + pageCount*(pageIndex-1)-1;
        System.out.println(fromMessage+""+pageCount);
        sourceBuilder.from(fromMessage);
        sourceBuilder.size(pageCount);
        //排序
        sourceBuilder.sort("filmscoring", SortOrder.DESC);
        //查询条件导入查询对象
        searchRequest.source(sourceBuilder);
        //执行查询
        SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        //获取返回结果集
        SearchHits hits = search.getHits();
        //迭代器进行迭代
        Iterator<SearchHit> iterator = hits.iterator();
        ArrayList<Filmresources> filmresourcess = new ArrayList<>();
        while (iterator.hasNext()){
            SearchHit hit = iterator.next();
            filmresourcess.add(JSON.parseObject(hit.getSourceAsString(), Filmresources.class));
        }
        return  filmresourcess;
    }

    /*关键词高亮条件搜索*/
    /**
     *
     * @param index  Es的index
     * @param keyword 用户搜索的关键词信息
     * @param pageIndex 查询的页数
     * @param pageCount 每页的数量
     * @param fields  参与搜索的字段名称
     * @return
     */
    public List<Filmresources> getByConditionHigh(String index,String keyword ,Integer pageIndex,Integer pageCount,String... fields) throws IOException {
        //创建查询结果高亮显示对象
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.preTags("<font color='red'>").postTags("</font>");//高亮标签
        highlightBuilder.fragmentSize(500);//高亮内容长度
        //添加高亮字段
        for(String field:fields){
            highlightBuilder.field(field);
        }

        //创建查询对象
        SearchRequest searchRequest = new SearchRequest(index);
        //创建条件查询对象
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        //条件拼接对象
        BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery();
        //关键词以及查询字段导入
        MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(keyword, fields);
        //区间查询
        RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("filmscoring");
        rangeQueryBuilder.gt(8.0);
        rangeQueryBuilder.lt(9.7);
        //将所有的查询条件合并
        //must表示and ,should表示or,notmust表示not
        boolBuilder.must(multiMatchQueryBuilder);
        boolBuilder.must(rangeQueryBuilder);
        sourceBuilder.query(boolBuilder);

        //分页查询
        //页数与每页数量计算从那条记录开始
        Integer fromMessage = pageIndex + pageCount*(pageIndex-1)-1;
        sourceBuilder.from(fromMessage);
        sourceBuilder.size(pageCount);
        //排序
        sourceBuilder.sort("filmscoring", SortOrder.DESC);
        //插入高亮查询对象
        sourceBuilder.highlighter(highlightBuilder);
        //查询条件导入查询对象
        searchRequest.source(sourceBuilder);
        //执行查询
        SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        //获取返回结果集
        SearchHits hits = search.getHits();
        //迭代器进行迭代
        Iterator<SearchHit> iterator = hits.iterator();
        ArrayList<Filmresources> filmresourcess = new ArrayList<>();
        while (iterator.hasNext()){
            SearchHit hit = iterator.next();
            //获取高亮
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            //将对应字段进行高亮替换
            if (highlightFields!=null&&highlightFields.size()>0){
                for(String field:fields){
                    if(highlightFields.get(field)!=null&&highlightFields.get(field).getFragments().length>0){
                        sourceAsMap.put(field,highlightFields.get(field).getFragments()[0].toString());
                    }
                }
            }
            filmresourcess.add(JSON.parseObject(JSON.toJSONString(sourceAsMap), Filmresources.class));
        }
        return  filmresourcess;
    }
}
